package com.cysyz.mylib.utils;

import com.cysyz.mylib.utils.myassert.MyAssert;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

public class MyReflectionUtils extends ReflectionUtils{
    public static Class getActualType(Class clazz, int index){
        ParameterizedType genericSuperclass = (ParameterizedType) clazz.getGenericSuperclass();
        return (Class) genericSuperclass.getActualTypeArguments()[index];
    }

    public static Object getFieldValue(String fieldName, Object bean) {
        Field field = MyReflectionUtils.findField(bean.getClass(), fieldName);
        MyAssert.notNull(field);
        MyReflectionUtils.makeAccessible(field);
        return MyReflectionUtils.getField(field, bean);
    }

    public static void setFieldValue(Object target, String targetFieldName,
                                     Object fieldValue) {
        Field findField = MyReflectionUtils.findField(target.getClass(), targetFieldName);
        MyReflectionUtils.makeAccessible(findField);
        MyReflectionUtils.setField(findField, target, fieldValue);
    }

    public static void printBeanInfo(Object bean, String... fieldNames) {
        System.out.println("打印对象【"+bean.getClass().getName()+"】的信息");
        Field field = null;
        List<Object> justShowTypelist = new ArrayList<Object>();
        justShowTypelist.add(1);
        justShowTypelist.add(1.11);
        justShowTypelist.add(1.11f);
        justShowTypelist.add(1l);
        justShowTypelist.add("");
        for (Object justShowTOjbect : justShowTypelist) {
            if (bean.getClass() == justShowTOjbect.getClass()) {
                System.out.println(bean.toString());
                return;
            }
        }
        if (fieldNames.length == 0) {
            for (Field tField : bean.getClass().getDeclaredFields()) {
                printField(bean, tField);
            }
        } else {

            for (String name : fieldNames) {
                try {
                    field = bean.getClass().getDeclaredField(name);
                } catch (SecurityException e) {
                    e.printStackTrace();
                } catch (NoSuchFieldException e) {
                    e.printStackTrace();
                }
                printField(bean, field);
            }

        }
    }

    public static void printBeanInfo(Collection collection) {
        System.out.println("打印对象【"+collection.getClass().getName()+"】的信息");
        for (Object o : collection) {
            printBeanInfo(o);
        }
    }

    public static <E> void printBeanInfo(Collection<E> collection, String... fieldNames) {
        MyAssert.notNull(collection);
        for (Iterator<E> iterator = collection.iterator(); iterator.hasNext();) {
            E e = (E) iterator.next();
            MyReflectionUtils.printBeanInfo(e, fieldNames);
        }
    }

    private static void printField(Object bean, Field field) {
        StringBuffer fieldInfo;
        fieldInfo = new StringBuffer(field.getName());
        fieldInfo.append("[");
        fieldInfo.append(field.getType());
        fieldInfo.append("]");
        fieldInfo.append(":");
        try {
            if (!field.isAccessible()) {
                field.setAccessible(true);
            }
            fieldInfo.append(field.get(bean));
            System.out.println(fieldInfo);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public static void copyProperties(Object original, Object target, String... fieldNames) {
        MyAssert.notNullMulti(original, target, fieldNames);
        for (String fieldName : fieldNames) {
            String[] origAndTargetFieldNames = fieldName.split(":");
            if (origAndTargetFieldNames.length == 2 || origAndTargetFieldNames.length == 1) {
                String originalFieldName = null;
                String targetFieldName = null;
                if (origAndTargetFieldNames.length == 2) {
                    originalFieldName = origAndTargetFieldNames[0];
                    targetFieldName = origAndTargetFieldNames[1];
                } else if (origAndTargetFieldNames.length == 1) {
                    originalFieldName = targetFieldName = origAndTargetFieldNames[0];
                }
                Object fieldValue = MyReflectionUtils.getFieldValue(originalFieldName, original);
                setFieldValue(target, targetFieldName, fieldValue);
            } else {
                throw new IllegalArgumentException("fieldNames格式错误，必须是【数据来源对象的属性名称】:【目标对象的属性名称】格式：" + origAndTargetFieldNames);
            }
        }
    }
}
